package com.lc.projects.unit.thread.part03.test1;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//多副本并发访问 Semaphore
public class Test2 {
	public static void main(String[] args) {
		PrintQueue2 printQueue = new PrintQueue2();
		Thread[] threads = new Thread[10];
		for (int i = 0; i < threads.length; i++) {
			threads[i] = new Thread(new Job2(printQueue),"Thread "+i);
		}
		
		for (int i = 0; i < threads.length; i++) {
			threads[i].start();
		}
	}
}

class PrintQueue2 {
	private final Semaphore semaphore;
	private Boolean[] freePrinters;
	private Lock lockPrinter;

	public PrintQueue2() {
		semaphore = new Semaphore(3);
		freePrinters = new Boolean[] { true, true, true };
		lockPrinter = new ReentrantLock();
	}

	public void printJob() {
		try {
			semaphore.acquire();
			int assigned = getPrinter();
			long duration = (long) (Math.random() * 10);
			System.out.println("PrintQueue " + assigned + " print job during " + duration + " seconds. name:"
					+ Thread.currentThread().getName());
			Thread.sleep(duration * 1000);
			freePrinters[assigned] = true;
	
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			semaphore.release();
		}
	}

	private int getPrinter() {
		int result = -1;
		try {
			lockPrinter.lock();
			for (int i = 0; i < freePrinters.length; i++) {
				if (freePrinters[i]) {
					result = i;
					freePrinters[i] = false;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lockPrinter.unlock();
		}

		return result;
	}

}


class Job2 implements Runnable{
	private PrintQueue2 printQueue;

	public Job2(PrintQueue2 printQueue) {
		super();
		this.printQueue = printQueue;
	}

	@Override
	public void run() {
		System.out.println("start print. name:" + Thread.currentThread().getName());
		printQueue.printJob();
		System.out.println("end print. name:" + Thread.currentThread().getName());
	}
	
}